package com.xy;

import android.util.Log;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.view.animation.TranslateAnimation;
import android.widget.TextView;

import com.nineoldandroids.animation.Animator;
import com.nineoldandroids.animation.AnimatorSet;
import com.nineoldandroids.animation.ObjectAnimator;
import com.nineoldandroids.animation.TypeEvaluator;
import com.nineoldandroids.animation.ValueAnimator;
import com.nineoldandroids.view.ViewHelper;
import com.xy.debug.SystemConfig;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/***
 * 简单动画方法类
 *
 * @author Y-bao
 */
public class AnimUtils {
    static HashMap<Object, Animator> map = new HashMap<>();

    public static void play(View view, Animator animator) {
        put(view, animator);
        animator.start();
    }

    public static void put(Object key, Animator value) {
        clear(key);
        map.put(key, value);
        Log.i("AnimUtils", map.size() + "");
    }

    public static Animator clear(Object key) {
        Animator old = null;
        if (map.containsKey(key)) {
            old = map.remove(key);
            old.getListeners().clear();
        }
        Log.i("AnimUtils", map.size() + "");
        return old;
    }

    public static Animator cancel(Object key) {
        Animator old = null;
        if (map.containsKey(key)) {
            old = map.remove(key);
            old.getListeners().clear();
            old.cancel();
        }
        Log.i("AnimUtils", map.size() + "");
        return old;
    }

    public static Animator remove(Object key) {
        Animator old = null;
        if (map.containsKey(key)) {
            old = map.remove(key);
        }
        Log.i("AnimUtils", map.size() + "");
        return old;
    }

    public static Animator getSildeY(View view, View hideView, float startY, float toY, int duration, boolean show, boolean hide, Interpolator interpolator) {
        Animator animator = ObjectAnimator.ofFloat(view, "TranslationY", startY, toY).setDuration(duration);
        animator.addListener(show ? new InAnimatorListener(view, hideView) : (hide ? new OutAnimatorListener(view, hideView) : new SimpleAnimatorListener(view)));
        if (interpolator != null) {
            animator.setInterpolator(interpolator);
        }
        return animator;
    }

    public static Animator getSildeX(View view, View hideView, float startX, float toX, int duration, boolean show, boolean hide, Interpolator interpolator) {
        Animator animator = ObjectAnimator.ofFloat(view, "TranslationX", startX, toX).setDuration(duration);
        animator.addListener(show ? new InAnimatorListener(view, hideView) : (hide ? new OutAnimatorListener(view, hideView) : new SimpleAnimatorListener(view)));
        if (interpolator != null) {
            animator.setInterpolator(interpolator);
        }
        return animator;
    }

    public static void sildeY(View view, float startY, float toY, int duration, boolean show, Interpolator interpolator) {
        Animator animator = getSildeY(view, null, startY, toY, duration, show, false, interpolator);
        play(view, animator);
    }

    public static void sildeX(View view, float startX, float toX, int duration, boolean show, Interpolator interpolator) {
        Animator animator = getSildeX(view, null, startX, toX, duration, show, false, interpolator);
        play(view, animator);
    }


    public static void sildeY(View view, int startHeigth, int toHeigth, int duration, boolean show) {
        sildeY(view, startHeigth, toHeigth, duration, show, null);
    }

    public static void sildeX(View view, int startX, int toX, int duration, boolean show) {
        sildeX(view, startX, toX, duration, show, null);
    }


    public static Animator getSildeToXAnim(View view, int toX, int duration, Interpolator interpolator) {
        Animator animator = ObjectAnimator.ofFloat(view, "TranslationX", ViewHelper.getTranslationX(view), toX).setDuration(duration);
        animator.addListener(new SimpleAnimatorListener(view));
        if (interpolator != null) {
            animator.setInterpolator(interpolator);
        }
        return animator;
    }

    public static Animator getSildeToYAnim(View view, int toY, int duration, Interpolator interpolator) {
        Animator animator = ObjectAnimator.ofFloat(view, "TranslationY", ViewHelper.getTranslationY(view), toY).setDuration(duration);
        animator.addListener(new SimpleAnimatorListener(view));
        if (interpolator != null) {
            animator.setInterpolator(interpolator);
        }
        return animator;
    }

    public static void sildeToX(View view, int toX) {
        sildeToX(view, toX, 300);
    }

    public static void sildeToY(View view, int toY) {
        sildeToY(view, toY, 300);
    }

    public static void sildeToX(View view, int toX, int duration) {
        sildeToX(view, toX, duration, null);
    }

    public static void sildeToY(View view, int toY, int duration) {
        sildeToY(view, toY, duration, null);
    }

    public static void sildeToX(View view, int toX, int duration, Interpolator interpolator) {
        Animator animator = getSildeToXAnim(view, toX, duration, interpolator);
        play(view, animator);
    }

    public static void sildeToY(View view, int toY, int duration, Interpolator interpolator) {
        Animator animator = getSildeToYAnim(view, toY, duration, interpolator);
        play(view, animator);
    }


    private static float getStartX(View view, int vector) {
        float width = view.getMeasuredWidth();
        int visibility = view.getVisibility();
        Log.i("testanim", "width:" + width + ",visibility:" + visibility);
        if (width == 0 || visibility == View.GONE) {
            view.setVisibility(View.VISIBLE);
            view.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
            width = view.getMeasuredWidth();
            Log.i("testanim", "width1:" + width * vector);
            return width * vector;
        } else if (visibility == View.VISIBLE) {
            float start = ViewHelper.getTranslationX(view);
            Log.i("testanim", "start:" + start + ",width2:" + view.getMeasuredWidth());
            return start;
        } else {
            Log.i("testanim", "else");
            return width * vector;
        }
    }

    private static float getStartY(View view, int vector) {
        float height = view.getMeasuredHeight();
        int visibility = view.getVisibility();
        if (height == 0 || visibility == View.GONE) {
            view.setVisibility(View.VISIBLE);
            view.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
            height = view.getMeasuredHeight();
            return height * vector;
        } else if (visibility == View.VISIBLE) {
            float start = ViewHelper.getTranslationY(view);
            return start;
        } else {
            return height * vector;
        }
    }

    private static float getEndX(View view, int vector) {
        float width = view.getMeasuredWidth();
        if (width == 0) {
            view.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
            width = view.getMeasuredWidth();
            return width * vector;
        } else {
            return width * vector;
        }
    }

    private static float getEndY(View view, int vector) {
        float height = view.getMeasuredHeight();
        if (height == 0) {
            view.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
            height = view.getMeasuredHeight();
            return height * vector;
        } else {
            return height * vector;
        }
    }

    public static void sildeOutToLeft(View view) {
        sildeOutToLeft(view, 300);
    }

    public static void sildeOutToLeft(View view, int duration) {
        sildeOutToLeft(view, view, duration);
    }

    public static void sildeOutToLeft(View view, View hideView, int duration) {
        float start = ViewHelper.getTranslationX(view);
        Animator animator = getSildeX(view, null, start, -hideView.getMeasuredWidth(), duration, false, view == hideView, null);
        play(view, animator);
    }

    public static void sildeOutToRight(View view) {
        sildeOutToRight(view, 300);
    }

    public static void sildeOutToRight(View view, int duration) {
        sildeOutToRight(view, view, duration);
    }

    public static void sildeOutToRight(View view, View hideView, int duration) {
        float start = ViewHelper.getTranslationX(view);
        Animator animator = getSildeX(view, null, start, hideView.getMeasuredWidth(), duration, false, view == hideView, null);
        play(view, animator);
    }

    public static void sildeOutToTop(View view) {
        sildeOutToTop(view, 300);
    }

    public static void sildeOutToTop(View view, int duration) {
        sildeOutToTop(view, view, duration);
    }

    public static void sildeOutToTop(View view, View hideView, int duration) {
        float start = ViewHelper.getTranslationY(view);
        Animator animator = getSildeY(view, null, start, -hideView.getMeasuredHeight(), duration, false, view == hideView, null);
        play(view, animator);
    }

    public static void sildeOutToBottom(View view) {
        sildeOutToBottom(view, 300);
    }

    public static void sildeOutToBottom(View view, int duration) {
        sildeOutToBottom(view, view, duration);
    }

    public static void sildeOutToBottom(View view, View hideView, int duration) {
        float start = ViewHelper.getTranslationY(view);
        Animator animator = getSildeY(view, null, start, hideView.getMeasuredHeight(), duration, false, view == hideView, null);
        play(view, animator);
    }


    public static void sildeInToLeft(View view) {
        sildeInToLeft(view, 300);
    }

    public static void sildeInToLeft(View view, int duration) {
        sildeInX(view, duration, -1, null);
    }

    public static void sildeInToLeft(View view, View hideView, int duration) {
        sildeInX(view, hideView, duration, -1, null);
    }

    public static void sildeInToRight(View view) {
        sildeInToRight(view, 300);
    }

    public static void sildeInToRight(View view, int duration) {
        sildeInX(view, duration, 1, null);
    }

    public static void sildeInToRight(View view, View hideView, int duration) {
        sildeInX(view, hideView, duration, 1, null);
    }

    public static void sildeInToTop(View view) {
        sildeInToTop(view, 300);
    }

    public static void sildeInToTop(View view, int duration) {
        sildeInY(view, duration, -1, null);
    }

    public static void sildeInToTop(View view, View hideView, int duration) {
        sildeInY(view, hideView, duration, -1, null);
    }

    public static void sildeInToBottom(View view) {
        sildeInToBottom(view, 300);
    }

    public static void sildeInToBottom(View view, int duration) {
        sildeInY(view, duration, 1, null);
    }

    public static void sildeInToBottom(View view, View hideView, int duration) {
        sildeInY(view, hideView, duration, 1, null);
    }

    public static void sildeInX(final View view, final int duration, final int vector, final Interpolator interpolator) {
        sildeInX(view, view, duration, vector, interpolator);
    }

    public static void sildeInY(final View view, final int duration, final int vector, final Interpolator interpolator) {
        sildeInY(view, view, duration, vector, interpolator);
    }

    public static void sildeInX(final View view, final View hideView, final int duration, final int vector, final Interpolator interpolator) {
        float width = hideView.getMeasuredWidth();
        int visibility = hideView.getVisibility();
        if (width == 0 || visibility == View.GONE) {
            hideView.setVisibility(View.VISIBLE);
            hideView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                @Override
                public void onGlobalLayout() {
                    float width = hideView.getMeasuredWidth();
                    if (width > 0) {
                        Animator animator = getSildeX(view, hideView, width * vector, 0, duration, true, false, interpolator);
                        play(view, animator);
                        SDKVersionHelper.removeOnGlobalLayoutListener(hideView.getViewTreeObserver(), this);
                    }
                }
            });
        } else if (visibility == View.VISIBLE) {
            float start = ViewHelper.getTranslationX(view);
            Animator animator = getSildeX(view, hideView, start, 0, duration, true, false, interpolator);
            play(view, animator);
        } else {
            Animator animator = getSildeX(view, hideView, width * vector, 0, duration, true, false, interpolator);
            play(view, animator);
        }
    }


    public static void sildeInY(final View view, final View hideView, final int duration, final int vector, final Interpolator interpolator) {
        float height = hideView.getMeasuredHeight();
        int visibility = hideView.getVisibility();
        if (height == 0 || visibility == View.GONE) {
            hideView.setVisibility(View.VISIBLE);
            hideView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                @Override
                public void onGlobalLayout() {
                    float height = hideView.getMeasuredHeight();
                    if (height > 0) {
                        Animator animator = getSildeY(view, hideView, height * vector, 0, duration, true, false, interpolator);
                        play(view, animator);
                        SDKVersionHelper.removeOnGlobalLayoutListener(hideView.getViewTreeObserver(), this);
                    }
                }
            });
        } else if (visibility == View.VISIBLE) {
            float start = ViewHelper.getTranslationY(view);
            Animator animator = getSildeY(view, hideView, start, 0, duration, true, false, interpolator);
            play(view, animator);
        } else {
            Animator animator = getSildeY(view, hideView, height * vector, 0, duration, true, false, interpolator);
            play(view, animator);
        }
    }

//    public static void sildeOutX(final View view, final View hideView, final int duration, final int vector, final Interpolator interpolator) {
//        Animator animator = getSildeX(view, getStartX(hideView, vector), 0, duration, true, false, interpolator);
//        play(view, animator);
//    }
//
//    public static void sildeOutY(final View view, final View hideView, final int duration, final int vector, final Interpolator interpolator) {
//        Animator animator = getSildeY(view, getStartY(hideView, vector), 0, duration, true, false, interpolator);
//        play(view, animator);
//    }


    public static void sildeOutToTops(View... views) {
        sildeOutToTops(300, views);
    }

    public static void sildeOutToTops(int duration, View... views) {
        if (views == null || views.length == 0) {
            return;
        }
        View view = views[0];
        float start = ViewHelper.getTranslationY(view);
        ofFloats(views, "TranslationY", duration, start, -view.getMeasuredHeight()).start();
    }


    public static void sildeInToTops(View... views) {
        sildeInToTops(300, views);
    }

    public static void sildeInToTops(int duration, View... views) {
        sildeInsY(duration, -1, views);
    }

    public static void sildeInsX(final int duration, final int vector, final View... views) {
        if (views == null || views.length == 0) {
            return;
        }
        final String translationName = "TranslationX";
        final View view = views[0];
        ofFloats(views, translationName, duration, getStartX(view, vector), 0).start();
    }

    public static void sildeInsY(final int duration, final int vector, final View... views) {
        if (views == null || views.length == 0) {
            return;
        }
        final String translationName = "TranslationY";
        final View view = views[0];
        ofFloats(views, translationName, duration, getStartY(view, vector), 0).start();
    }

    public static AnimatorSet ofFloats(Object[] objects, String propertyName, int duration, float... values) {
        AnimatorSet animatorSet = new AnimatorSet();
        List<Animator> list = new ArrayList<>();
        for (Object obj : objects) {
            Animator animator = ObjectAnimator.ofFloat(obj, propertyName, values).setDuration(duration);
            animator.addListener(new SimpleAnimatorListener(obj));
            put(obj, animator);
            list.add(animator);
            if (obj instanceof View) {
                ((View) obj).setVisibility(View.VISIBLE);
            }
        }
        animatorSet.playTogether(list);
        return animatorSet;
    }

    static class SimpleAnimatorListener implements Animator.AnimatorListener {
        Object object;

        public SimpleAnimatorListener(Object object) {
            this.object = object;
        }

        @Override
        public void onAnimationStart(Animator animation) {
        }

        @Override
        public void onAnimationEnd(Animator animation) {
            remove(object);
        }

        @Override
        public void onAnimationCancel(Animator animation) {
            remove(object);
        }

        @Override
        public void onAnimationRepeat(Animator animation) {

        }
    }


    static class OutAnimatorListener extends SimpleAnimatorListener {
        View view;

        public OutAnimatorListener(View view) {
            super(view);
            this.view = view;
        }

        public OutAnimatorListener(View view, View hideView) {
            super(view);
            this.view = hideView == null ? view : hideView;
        }

        @Override
        public void onAnimationStart(Animator animation) {
            super.onAnimationStart(animation);
        }

        @Override
        public void onAnimationEnd(Animator animation) {
            super.onAnimationEnd(animation);
            view.setVisibility(View.GONE);
        }
    }


    static class InAnimatorListener extends SimpleAnimatorListener {
        View view;

        public InAnimatorListener(View view) {
            super(view);
            this.view = view;
        }

        public InAnimatorListener(View view, View hideView) {
            super(view);
            this.view = hideView == null ? view : hideView;
        }

        @Override
        public void onAnimationStart(Animator animation) {
            super.onAnimationStart(animation);
            view.setVisibility(View.VISIBLE);
        }

    }

    public static void startToRotation(View view, float toRotation) {
        float nowR = ViewHelper.getRotation(view);
        ObjectAnimator animator = ObjectAnimator.ofFloat(view, "rotation", nowR, toRotation);
        animator.addListener(new SimpleAnimatorListener(view));
        animator.start();
    }

    public static void startRotation(View view, float dtRotation, long duration, long startDelay) {
        float nowR = ViewHelper.getRotation(view);
        ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(view, "rotation", nowR,
                nowR + dtRotation).setDuration(duration);
        objectAnimator.setStartDelay(startDelay);
        objectAnimator.start();
    }

    public static void startDistRotation(View view, float dtRotation, long duration, long startDelay, int times) {
        float nowR = ViewHelper.getRotation(view);
        ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(view, "rotation", nowR,
                nowR + dtRotation).setDuration(duration);
        objectAnimator.setStartDelay(startDelay);
        objectAnimator.setRepeatCount(times);
        objectAnimator.setInterpolator(new LinearInterpolator());
        objectAnimator.addListener(new SimpleAnimatorListener(view));
        put(view, objectAnimator);
        objectAnimator.start();
    }

    public static void startShow(View view) {
        startShow(view, 300);
    }

    public static void startShow(View view, long duration) {
        float alpha = ViewHelper.getAlpha(view);
        if (alpha < 1f || view.getVisibility() != View.VISIBLE) {
            ObjectAnimator animator = ObjectAnimator.ofFloat(view, "alpha", alpha, 1f).setDuration(duration);
            animator.addListener(new InAnimatorListener(view));
            put(view, animator);
            animator.start();
        }
    }

    public static void startHide(View view) {
        startHide(view, 300);
    }

    public static void startHide(View view, long duration) {
        float alpha = ViewHelper.getAlpha(view);
        if (alpha > 0f && view.getVisibility() == View.VISIBLE) {
            ObjectAnimator animator = ObjectAnimator.ofFloat(view, "alpha", alpha, 0f).setDuration(duration);
            animator.addListener(new OutAnimatorListener(view));
            put(view, animator);
            animator.start();
        }
    }


    public static void startScale(final View view, float toScale) {
        ObjectAnimator.ofFloat(view, "scaleX", ViewHelper.getScaleX(view), toScale).start();
        ObjectAnimator.ofFloat(view, "scaleY", ViewHelper.getScaleY(view), toScale).start();
    }

    public static void startScale(final View view, float toScale, long duration, long startDelay,
                                  Interpolator setInterpolator) {
        ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(view, "scaleX", ViewHelper.getScaleX(view), toScale)
                .setDuration(duration);
        objectAnimator.setStartDelay(startDelay);
        objectAnimator.setInterpolator(setInterpolator);
        objectAnimator.start();
        objectAnimator = ObjectAnimator.ofFloat(view, "scaleY", ViewHelper.getScaleY(view), toScale).setDuration(
                duration);
        objectAnimator.setStartDelay(startDelay);
        objectAnimator.setInterpolator(setInterpolator);
        objectAnimator.start();
    }

    public static void startScale(final View view, float fromScale, float toScale) {
        ObjectAnimator.ofFloat(view, "scaleX", fromScale, toScale).start();
        ObjectAnimator.ofFloat(view, "scaleY", fromScale, toScale).start();
    }

    public static void startScale(final View view, float fromScale, float toScale, long duration, long startDelay,
                                  Interpolator setInterpolator) {
        ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(view, "scaleX", fromScale, toScale)
                .setDuration(duration);
        objectAnimator.setStartDelay(startDelay);
        objectAnimator.setInterpolator(setInterpolator);
        objectAnimator.start();
        objectAnimator = ObjectAnimator.ofFloat(view, "scaleY", fromScale, toScale).setDuration(duration);
        objectAnimator.setStartDelay(startDelay);
        objectAnimator.setInterpolator(setInterpolator);
        objectAnimator.start();
    }

    public static void startFromY(final View view, float fromY) {
        ObjectAnimator.ofFloat(view, "translationY", fromY, 0).start();
    }

    public static void startToY(final View view, float toY) {
        ObjectAnimator.ofFloat(view, "translationY", 0, toY).start();
    }


    public static void parabola2(View view, int[] startP, int[] endP, int duration) {
        //        PropertyValuesHolder phX = PropertyValuesHolder.ofFloat("x", startP[0], endP[0]);
        //        PropertyValuesHolder phY = PropertyValuesHolder.ofFloat("y", startP[1], endP[1]);
        Animator animatorX = ObjectAnimator.ofFloat(view, "x", startP[0], endP[0]);
        Animator animatorY = ObjectAnimator.ofFloat(view, "y", startP[1], endP[1]);
        animatorY.setDuration(duration);
        animatorX.setDuration(duration);
        animatorY.start();
        animatorX.start();
    }

    public static void parabola(final View view, int[] startP, int[] endP, int duration) {

        TranslateAnimation translateAnimationX = new TranslateAnimation(startP[0], endP[0], 0, 0);
        TranslateAnimation translateAnimationY = new TranslateAnimation(0, 0, startP[1], endP[1]);
        translateAnimationX.setFillAfter(true);
        translateAnimationX.setRepeatCount(0);
        translateAnimationY.setFillAfter(true);
        translateAnimationY.setRepeatCount(0);
        translateAnimationX.setInterpolator(new AccelerateInterpolator());
        translateAnimationY.setInterpolator(new LinearInterpolator());
        AnimationSet flySet = new AnimationSet(false);
        flySet.addAnimation(translateAnimationX);
        flySet.addAnimation(translateAnimationY);
        flySet.setDuration(duration);
        flySet.setFillAfter(false);
        view.setAnimation(flySet);
        flySet.setAnimationListener(new Animation.AnimationListener() {

            @Override
            public void onAnimationStart(Animation animation) {
                view.setVisibility(View.VISIBLE);
            }

            @Override
            public void onAnimationRepeat(Animation animation) {
            }

            @Override
            public void onAnimationEnd(Animation animation) {
                view.setVisibility(View.GONE);
            }
        });
    }


    public static void startNemScrollInt(final TextView view, int start, int nem) {
        startNemScrollInt(view, start, nem, 300, 1000);
    }

    public static void startNemScrollInt(final TextView view, int start, int nem, int startDelay, int duration) {
        startNemScrollInt(view, start, nem, startDelay, duration, null);
    }

    public static void startNemScrollInt(final TextView view, int start, int nem, int startDelay, int duration, Interpolator interpolator) {
        if (start == nem) {
            view.setText(nem + "");
            return;
        }
        ValueAnimator valueAnimator = ValueAnimator.ofObject(new TypeEvaluator() {
            @Override
            public Object evaluate(float fraction, Object startValue, Object endValue) {
                int start = Integer.parseInt(startValue.toString());
                int end = Integer.parseInt(endValue.toString());
                int ee = (int) ((end - start) * fraction + start);
                return ee;
            }
        }, start, nem);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                view.setText(animation.getAnimatedValue().toString());
            }
        });
        valueAnimator.setStartDelay(startDelay);
        valueAnimator.setDuration(duration);
        if (interpolator != null) {
            valueAnimator.setInterpolator(interpolator);
        }
        valueAnimator.start();
    }

    public static void startNemScrollDouble(final TextView view, double start, double nem, DecimalFormat decimalFormat) {
        startNemScrollDouble(view, start, nem, 300, 1000, decimalFormat);
    }

    public static void startNemScrollDouble(final TextView view, double start, double nem, int startDelay, int duration, DecimalFormat decimalFormat) {
        startNemScrollDouble(view, start, nem, startDelay, duration, null, decimalFormat);
    }

    public static void startNemScrollDouble(final TextView view, double start, double nem, int startDelay, int duration, Interpolator interpolator, final DecimalFormat decimalFormat) {
        BigDecimal data1 = new BigDecimal(start);
        BigDecimal data2 = new BigDecimal(nem);
        if (data1.compareTo(data2) == 0) {
            view.setText(decimalFormat.format(nem));
            return;
        }
        ValueAnimator valueAnimator = ValueAnimator.ofObject(new TypeEvaluator() {
            @Override
            public Object evaluate(float fraction, Object startValue, Object endValue) {
                double start = Double.parseDouble(startValue.toString());
                double end = Double.parseDouble(endValue.toString());
                double ee = (end - start) * fraction + start;
                return ee;
            }
        }, start, nem);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                view.setText(decimalFormat.format(animation.getAnimatedValue()));
            }
        });
        valueAnimator.setStartDelay(startDelay);
        valueAnimator.setDuration(duration);
        if (interpolator != null) {
            valueAnimator.setInterpolator(interpolator);
        }
        valueAnimator.start();
    }


    public static void gravityDown(View view, Animator.AnimatorListener animatorListener) {
        view.setVisibility(View.VISIBLE);
        int startY = SystemConfig.getScreenHeight(view.getContext());
        int midY = SystemConfig.dp2px(view.getContext(), 20);

        AccelerateInterpolator accelerateInterpolator = new AccelerateInterpolator();
        LinearInterpolator linearInterpolator = new LinearInterpolator();

        ObjectAnimator translationY1 = ObjectAnimator.ofFloat(view, "translationY", -startY, midY);
        translationY1.setInterpolator(accelerateInterpolator);
        translationY1.setDuration(500);

        ObjectAnimator alpha = ObjectAnimator.ofFloat(view, "alpha", 0, 1);
        alpha.setInterpolator(accelerateInterpolator);
        alpha.setDuration(500);

        ObjectAnimator rotation1 = ObjectAnimator.ofFloat(view, "rotation", 0, 1);
        rotation1.setInterpolator(accelerateInterpolator);
        rotation1.setDuration(200);
        rotation1.setStartDelay(300);

        ObjectAnimator translationY2 = ObjectAnimator.ofFloat(view, "translationY", midY, 0);
        translationY2.setInterpolator(linearInterpolator);
        translationY2.setDuration(200);
        translationY2.setStartDelay(500);

        ObjectAnimator rotation2 = ObjectAnimator.ofFloat(view, "rotation", 1, 0);
        rotation2.setInterpolator(linearInterpolator);
        rotation2.setDuration(200);
        rotation2.setStartDelay(500);

        AnimatorSet animatorSet = new AnimatorSet();
        animatorSet.addListener(animatorListener);
        animatorSet.play(translationY1).with(alpha).with(rotation1).with(translationY2).with(rotation2);
        animatorSet.start();
    }

    public static void gravityUp(View view, Animator.AnimatorListener animatorListener) {
        int startY = SystemConfig.getScreenHeight(view.getContext());
        int midY = SystemConfig.dp2px(view.getContext(), 20);

        AccelerateInterpolator accelerateInterpolator = new AccelerateInterpolator();
        LinearInterpolator linearInterpolator = new LinearInterpolator();

        ObjectAnimator translationY1 = ObjectAnimator.ofFloat(view, "translationY", 0, midY);
        translationY1.setInterpolator(linearInterpolator);
        translationY1.setDuration(400);

        ObjectAnimator rotation1 = ObjectAnimator.ofFloat(view, "rotation", 0, 1);
        rotation1.setInterpolator(linearInterpolator);
        rotation1.setDuration(400);


        ObjectAnimator translationY2 = ObjectAnimator.ofFloat(view, "translationY", midY, -startY);
        translationY2.setInterpolator(accelerateInterpolator);
        translationY2.setDuration(400);
        translationY2.setStartDelay(400);

        ObjectAnimator rotation2 = ObjectAnimator.ofFloat(view, "rotation", 1, 0);
        rotation2.setInterpolator(accelerateInterpolator);
        rotation2.setDuration(300);
        rotation2.setStartDelay(400);

        ObjectAnimator alpha = ObjectAnimator.ofFloat(view, "alpha", 1, 0);
        alpha.setInterpolator(accelerateInterpolator);
        alpha.setDuration(400);
        alpha.setStartDelay(400);

        AnimatorSet animatorSet = new AnimatorSet();
        animatorSet.addListener(animatorListener);
        animatorSet.play(translationY1).with(rotation1).with(translationY2).with(rotation2).with(alpha);
        animatorSet.start();
    }
}
